package com.norman.sorry.core.moves;

import java.util.Arrays;
import java.util.Collection;

import com.norman.sorry.core.pieces.IPiece;
import com.norman.sorry.core.tiles.ILinkedTile;

/**
 * A final factory class that provides methods to create different types of
 * moves.
 * 
 * @author Brian Norman
 * @version 0.0.1 beta
 * @since 0.0.1 beta
 */
public final class MoveFactory {

   /**
    * Private constructor so no one can create an instance of this class.
    */
   private MoveFactory() {
   }

   /**
    * Returns a new move that represents a game piece moving to a new tile.
    * 
    * @param piece
    *           the game piece that is moving.
    * @param tile
    *           the tile the game piece is moving to.
    * @return a new move that moves the game piece to the new tile.
    */
   public static IMove createSingleMove(final IPiece piece, final ILinkedTile tile) {
      if (piece != null && tile != null) {
         final Collection<IPiece> pieces = Arrays.asList(piece);
         return new AbstractMove(null) {
            @Override
            public ILinkedTile getTile(IPiece p) {
               if (piece.equals(p)) {
                  return tile;
               } else {
                  return null;
               }
            }

            @Override
            public Collection<IPiece> getPieces() {
               return pieces;
            }
         };
      } else {
         return null;
      }
   }

   /**
    * Returns a new move that represents two game pieces moving each to their
    * new respective tiles.
    * 
    * @param piece1
    *           the first game piece that is moving.
    * @param tile1
    *           the tile the first game piece is moving to.
    * @param piece2
    *           the second game piece that is moving.
    * @param tile2
    *           the tile the second game piece is moving to.
    * @return a new move that moves both game pieces to their new tiles.
    */
   public static IMove createDoubleMove(final IPiece piece1, final ILinkedTile tile1, final IPiece piece2,
         final ILinkedTile tile2) {
      if (piece1 != null && tile1 != null && piece2 != null && tile2 != null) {
         final Collection<IPiece> pieces = Arrays.asList(piece1, piece2);
         return new AbstractMove(null) {
            @Override
            public ILinkedTile getTile(IPiece p) {
               if (piece1.equals(p)) {
                  return tile1;
               } else if (piece2.equals(p)) {
                  return tile2;
               } else {
                  return null;
               }
            }

            @Override
            public Collection<IPiece> getPieces() {
               return pieces;
            }
         };
      } else {
         return null;
      }
   }

   /**
    * Returns a new move that represents two game pieces switching tiles.
    * 
    * @param piece1
    *           the first game piece that is moving.
    * @param tile1
    *           the tile the first game piece is at.
    * @param piece2
    *           the second game piece that is moving.
    * @param tile2
    *           the tile the second game piece is at.
    * @return a new move that moves both game pieces to their new tiles.
    */
   public static IMove createSwitchMove(final IPiece piece1, final ILinkedTile tile1, final IPiece piece2,
         final ILinkedTile tile2) {
      return createDoubleMove(piece1, tile2, piece2, tile1);
   }

}
